package com.hollycrm.springframework.dbaccesslog.hibernate;

import java.lang.reflect.Method;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.hollycrm.springframework.dbaccesslog.DBAccessLog;
import com.hollycrm.springframework.dbaccesslog.DBAccessManager;
import com.hollycrm.springframework.factory.DefaultBeanFactory;

public class HibernateTemplateInterceptor
    implements MethodInterceptor {

    protected final Log logger = LogFactory.getLog(getClass());
    protected boolean logEnable = false;

    /**
     * invoke
     *
     * @param methodInvocation MethodInvocation
     * @return Object
     * @throws Throwable
     */
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        if (logEnable) {
            boolean isOK = false;
            DBAccessLog dbAccessLog = null;
            DBAccessManager dbAccessManager = (DBAccessManager)
                DefaultBeanFactory.getBean(DBAccessManager.BEAN_ID);
            try {
                try {
                    Method mm = this.getClass().getDeclaredMethod("log_" +
                        methodInvocation.getMethod().getName(),
                        new Class[] {DBAccessManager.class, MethodInvocation.class, });
                    dbAccessLog = (DBAccessLog) mm.invoke(this,
                        new Object[] {dbAccessManager, methodInvocation, });
                }
                catch (Exception e) {
                    logger.warn("[w] " + e.getMessage());
                }

                Object retVal = methodInvocation.proceed();

                isOK = true;
                return retVal;
            }
            finally {
                logger.debug("DBAccessInterceptor: " +
                             methodInvocation.getMethod().getDeclaringClass() +
                             "->" + methodInvocation.getMethod().getName());
                if (dbAccessLog != null) {
                    try {
                        dbAccessManager.saveLog(dbAccessLog, isOK);
                    }
                    catch (Exception ex) {
                        logger.warn("[w] " + ex.getMessage());
                    }
                }
            }
        }
        else {
            return methodInvocation.proceed();
        }
    }

    public DBAccessLog log_createQuery(DBAccessManager dbAccessManager,
                                       MethodInvocation methodInvocation) throws
        Exception {
        return dbAccessManager.initialLog("log_createQuery",
                                          "" +
                                          methodInvocation.getArguments()[1]);
    }

    public DBAccessLog log_find(DBAccessManager dbAccessManager,
                                MethodInvocation methodInvocation) throws
        Exception {
        return dbAccessManager.initialLog("log_find",
                                          "" +
                                          methodInvocation.getArguments()[0]);
    }

    public DBAccessLog log_findByNamedQuery(DBAccessManager dbAccessManager,
                                            MethodInvocation methodInvocation) throws
        Exception {
        return dbAccessManager.initialLog("log_findByNamedQuery",
                                          "" +
                                          methodInvocation.getArguments()[0]);
    }

    public DBAccessLog log_get(DBAccessManager dbAccessManager,
                               MethodInvocation methodInvocation) throws
        Exception {
        return dbAccessManager.initialLog("log_get",
                                          "get " +
                                          methodInvocation.getArguments()[0]);
    }

    public DBAccessLog log_load(DBAccessManager dbAccessManager,
                                MethodInvocation methodInvocation) throws
        Exception {
        return dbAccessManager.initialLog("log_load",
                                          "load " +
                                          methodInvocation.getArguments()[0]);
    }

    public DBAccessLog log_loadAll(DBAccessManager dbAccessManager,
                                   MethodInvocation methodInvocation) throws
        Exception {
        return dbAccessManager.initialLog("log_loadAll",
                                          "loadAll " +
                                          methodInvocation.getArguments()[0]);
    }

    public DBAccessLog log_save(DBAccessManager dbAccessManager,
                                MethodInvocation methodInvocation) throws
        Exception {
        return dbAccessManager.initialLog("log_save",
                                          "save " +
                                          methodInvocation.getArguments()[0]);
    }

    public DBAccessLog log_saveOrUpdate(DBAccessManager dbAccessManager,
                                        MethodInvocation methodInvocation) throws
        Exception {
        return dbAccessManager.initialLog("log_saveOrUpdate",
                                          "saveOrUpdate " +
                                          methodInvocation.getArguments()[0]);
    }

    public DBAccessLog log_saveOrUpdateCopy(DBAccessManager dbAccessManager,
                                            MethodInvocation methodInvocation) throws
        Exception {
        return dbAccessManager.initialLog("log_saveOrUpdateCopy",
                                          "saveOrUpdateCopy " +
                                          methodInvocation.getArguments()[0]);
    }

    public DBAccessLog log_update(DBAccessManager dbAccessManager,
                                  MethodInvocation methodInvocation) throws
        Exception {
        return dbAccessManager.initialLog("log_update",
                                          "update " +
                                          methodInvocation.getArguments()[0]);
    }

    public DBAccessLog log_delete(DBAccessManager dbAccessManager,
                                  MethodInvocation methodInvocation) throws
        Exception {
        return dbAccessManager.initialLog("log_delete",
                                          "delete " +
                                          methodInvocation.getArguments()[0]);
    }

    public DBAccessLog log_deleteAll(DBAccessManager dbAccessManager,
                                     MethodInvocation methodInvocation) throws
        Exception {
        return dbAccessManager.initialLog("log_deleteAll",
                                          "deleteAll " +
                                          methodInvocation.getArguments()[0]);
    }

    public DBAccessLog log_createCriteria(DBAccessManager dbAccessManager,
                                          MethodInvocation methodInvocation) throws
        Exception {
        return dbAccessManager.initialLog("log_createCriteria",
                                          "createCriteria " +
                                          methodInvocation.getArguments()[0]);
    }

    public DBAccessLog log_getNamedQuery(DBAccessManager dbAccessManager,
                                         MethodInvocation methodInvocation) throws
        Exception {
        return dbAccessManager.initialLog("log_getNamedQuery",
                                          "getNamedQuery " +
                                          methodInvocation.getArguments()[0]);
    }

    public DBAccessLog log_evict(DBAccessManager dbAccessManager,
                                 MethodInvocation methodInvocation) throws
        Exception {
        return null;
    }

    public DBAccessLog log_lock(DBAccessManager dbAccessManager,
                                MethodInvocation methodInvocation) throws
        Exception {
        return null;
    }

    public DBAccessLog log_isAllowCreate(DBAccessManager dbAccessManager,
                                         MethodInvocation methodInvocation) throws
        Exception {
        return null;
    }

    public DBAccessLog log_execute(DBAccessManager dbAccessManager,
                                         MethodInvocation methodInvocation) throws
        Exception {
        return null;
    }

    public DBAccessLog log_executeFind(DBAccessManager dbAccessManager,
                                         MethodInvocation methodInvocation) throws
        Exception {
        return null;
    }

    public boolean isLogEnable() {
        return logEnable;
    }
    public void setLogEnable(boolean logEnable) {
        this.logEnable = logEnable;
    }

}
